use dirs;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io::Write;
use tauri::{AppHandle, Emitter};

// 定义全局常量
const APP_IDENTIFIER: &str = "com.red-shore.app";
const SESSION_DIR: &str = "session";
const SESSION_FILE: &str = "session.data";
const CONFIG_DIR: &str = "config";
const CONFIG_FILE: &str = "base-config.data";

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BaseConfig {
    language: String,
    theme: String,
    page_title: String,
    page_title_update_interval: u32,
    status_update_interval: u32,
    task_info_update_interval: u32,
    task_delete_confirm: String,
}

impl Default for BaseConfig {
    fn default() -> Self {
        BaseConfig {
            language: "简体中文".to_string(),
            theme: "浅色".to_string(),
            page_title: "${downspeed}, ${upspeed} - ${title}".to_string(),
            page_title_update_interval: 5,
            status_update_interval: 1,
            task_info_update_interval: 1,
            task_delete_confirm: "启用".to_string(),
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DownloadList {
    downloads: Vec<Download>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Download {
    pub id: u32,
    pub url: String,
    pub file_name: String,
    pub path: String,
    pub size: String,
    pub status: String,
    pub progress: f64,
    pub total_bytes: u64,
    pub thread_progress: Vec<ThreadProgress>,
}
use crate::download_manager::ThreadProgress;

pub fn initialize_config() -> Result<(), Box<dyn std::error::Error>> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let config_dir = project_dir.join(CONFIG_DIR);

    if !config_dir.exists() {
        fs::create_dir_all(&config_dir)?
    }

    let config_file = config_dir.join(CONFIG_FILE);
    if !config_file.exists() {
        let config = BaseConfig::default();
        let mut file = fs::File::create(&config_file)?;
        let json_data = serde_json::to_string_pretty(&config)?;
        file.write_all(json_data.as_bytes())?;
    }

    Ok(())
}

pub fn initialize_session() -> Result<(), Box<dyn std::error::Error>> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);

    if !project_dir.exists() {
        fs::create_dir_all(&project_dir)?
    }

    let session_dir = project_dir.join(SESSION_DIR);
    if !session_dir.exists() {
        fs::create_dir_all(&session_dir)?
    }

    let session_file = session_dir.join(SESSION_FILE);
    if !session_file.exists() {
        let download_list = DownloadList { downloads: vec![] };

        let mut file = fs::File::create(&session_file)?;
        let json_data = serde_json::to_string_pretty(&download_list)?;
        file.write_all(json_data.as_bytes())?;
    }

    Ok(())
}
#[tauri::command]
pub async fn save_download_task(id: u32, download: Download) -> Result<String, String> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let session_dir = project_dir.join(SESSION_DIR);
    let session_file = session_dir.join(SESSION_FILE);

    // 读取现有的下载列表
    let mut download_list = match fs::read_to_string(&session_file) {
        Ok(data) => match serde_json::from_str::<DownloadList>(&data) {
            Ok(list) => list,
            Err(e) => return Err(format!("Failed to parse session data: {}", e)),
        },
        Err(e) => return Err(format!("Failed to read session file: {}", e)),
    };

    // 更新或添加下载任务
    if let Some(existing_download) = download_list.downloads.iter_mut().find(|d| d.id == id) {
        *existing_download = download;
    } else {
        download_list.downloads.push(download);
    }

    // 保存更新后的下载列表
    let mut file = match fs::File::create(&session_file) {
        Ok(f) => f,
        Err(e) => return Err(format!("Failed to create file: {}", e)),
    };
    let json_data = match serde_json::to_string_pretty(&download_list) {
        Ok(data) => data,
        Err(e) => return Err(format!("Failed to serialize data: {}", e)),
    };
    if let Err(e) = file.write_all(json_data.as_bytes()) {
        return Err(format!("Failed to write to file: {}", e));
    }

    Ok("Download task saved successfully".to_string())
}
#[tauri::command]
pub fn update_session_data(downloads: Vec<Download>) -> Result<String, String> {
    println!("update_session_data");
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let session_dir = project_dir.join(SESSION_DIR);
    let session_file = session_dir.join(SESSION_FILE);

    let download_list = DownloadList { downloads };
    let mut file = match fs::File::create(&session_file) {
        Ok(f) => f,
        Err(e) => return Err(format!("Failed to create file: {}", e)),
    };
    let json_data = match serde_json::to_string_pretty(&download_list) {
        Ok(data) => data,
        Err(e) => return Err(format!("Failed to serialize data: {}", e)),
    };
    if let Err(e) = file.write_all(json_data.as_bytes()) {
        return Err(format!("Failed to write to file: {}", e));
    }

    Ok("Session data updated successfully".to_string())
}

#[tauri::command]
pub fn get_config() -> Result<BaseConfig, String> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let config_dir = project_dir.join(CONFIG_DIR);
    let config_file = config_dir.join(CONFIG_FILE);

    let config_data = match fs::read_to_string(&config_file) {
        Ok(data) => data,
        Err(e) => return Err(format!("Failed to read config file: {}", e)),
    };

    match serde_json::from_str(&config_data) {
        Ok(config) => Ok(config),
        Err(e) => Err(format!("Failed to parse config data: {}", e)),
    }
}
#[tauri::command]
pub fn get_session_data() -> Result<DownloadList, String> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let session_dir = project_dir.join(SESSION_DIR);
    let session_file = session_dir.join(SESSION_FILE);

    let session_data = match fs::read_to_string(&session_file) {
        Ok(data) => data,
        Err(e) => return Err(format!("Failed to read session file: {}", e)),
    };

    let download_list: DownloadList = match serde_json::from_str(&session_data) {
        Ok(list) => list,
        Err(e) => return Err(format!("Failed to parse session data: {}", e)),
    };

    // 将下载任务添加到DOWNLOAD_MANAGER中
    if let Ok(rt) = tokio::runtime::Runtime::new() {
        for download in &download_list.downloads {
            if let Err(e) = rt.block_on(async {
                let _ = crate::download_manager::DOWNLOAD_MANAGER
                    .restore_task(download.id, download.url.clone(), download.file_name.clone(), download.path.clone(), download.thread_progress.clone())
                    .await;
                Ok::<(), String>(())
            }) {
                println!("Failed to restore task to DOWNLOAD_MANAGER: {}", e);
            }
        }
    }

    Ok(download_list)
}
#[tauri::command]
pub fn update_config(config: BaseConfig) -> Result<String, String> {
    let app_data_dir = dirs::data_dir().ok_or("Unable to get AppData directory")?;
    let project_dir = app_data_dir.join(APP_IDENTIFIER);
    let config_dir = project_dir.join(CONFIG_DIR);
    let config_file = config_dir.join(CONFIG_FILE);

    let mut file = match fs::File::create(&config_file) {
        Ok(f) => f,
        Err(e) => return Err(format!("Failed to create config file: {}", e)),
    };

    let json_data = match serde_json::to_string_pretty(&config) {
        Ok(data) => data,
        Err(e) => return Err(format!("Failed to serialize config data: {}", e)),
    };

    if let Err(e) = file.write_all(json_data.as_bytes()) {
        return Err(format!("Failed to write config file: {}", e));
    }

    Ok("Config updated successfully".to_string())
}
